package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @Author LEO
 * @Date 2021年12月20日 19:36
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo> implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${ware.url}")
    private String wareUrl;

    @Autowired
    private RabbitService rabbitService;


    //保存订单
    @Override
    public Long saveOrderInfo(OrderInfo orderInfo) {
        /**
         * 1. orderInfo orderDetail
         * 前台未赋值 需要手动设置 order_info表
         */
        //总金额  ：单价* 数量
        orderInfo.sumTotalAmount(); //自动赋值
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //在实现类能否获取userId ,不能   在控制器获取
        // 第三方交易编号要求唯一
        String outTradeNo="ATGUIGU"+System.currentTimeMillis()+""+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述
        orderInfo.setTradeBody("有钱就想花，就是玩");
        // 可以将送货清单中的skuName 进行拼接 ！ 放入TradeBody中
        orderInfo.setCreateTime(new Date());
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,1);
        orderInfo.setExpireTime(calendar.getTime());  //设置24小时过期
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        orderInfoMapper.insert(orderInfo);
        //获取订单明细
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }
        long orderId= orderInfo.getId();
        // 返回订单id
        //发送消息 消息主体 订单id                             MqConst.DELAY_TIME 延迟时间
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,MqConst.ROUTING_ORDER_CANCEL,orderId,MqConst.DELAY_TIME);
        return orderId;
    }


    @Override
    public String getTradeNo(String userId) {
        //制作流水号
        String tradeNo = UUID.randomUUID().toString();
        //存储到缓存中
        String tradeNoKey="user"+userId+":tradeCode";
        redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }

    @Override
    public Boolean checkTradeNo(String tradeNo, String userId) {
        // 获取缓存的key
        String tradeNoKey="user"+userId+":tradeCode";
        String tradeNoRedis = (String) redisTemplate.opsForValue().get(tradeNoKey);
       //  比较并返回结果
        return tradeNo.equals(tradeNoRedis);
    }

    @Override
    public void deleteTradeNo(String userId) {
        // 获取缓存的key
        String tradeNoKey="user"+userId+":tradeCode";
        redisTemplate.delete(tradeNoKey);
    }


    @Override
    public Boolean checkStock(Long skuId, Integer skuNum) {
        //http://localhost:9001/hasStock?skuId=10221&num=2
        String result=   HttpClientUtil.doGet(wareUrl+"/hasStock?skuId="+skuId+"&num"+skuNum);
        //0：无库存   1：有库存     true 有
        return "1".equals(result);
    }

    //修改订单状态
    @Override
    public void execExpiredOrder(Long orderId) {

         updateOrderStatus(orderId,ProcessStatus.CLOSED);
        // 后续可能需要更新订单进度状态，还需要更新订单状态
        // /**
        // * 根据订单Id 修改订单的状态
        // * @param orderId
        // * @param processStatus
        // */
        //void updateOrderStatus(Long orderId, ProcessStatus processStatus);

        // 发送一个消息关闭交易记录
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);

    }


    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        // 从订单进度状态中获取订单状态
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setId(orderId);
        orderInfoMapper.updateById(orderInfo);
    }

    /**
     * 根据订单Id 查询订单信息
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        // 后续可能需要到订单明细
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id", orderId));
        if (orderInfo !=null){
            orderInfo.setOrderDetailList(orderDetailList);
        }
        return orderInfo;
    }

    /**
     * 发送消息给库存！
     * @param orderId
     */
    @Override
    public void sendOrderStatus(Long orderId) {
        // 修改订单状态
        this.updateOrderStatus(orderId,ProcessStatus.NOTIFIED_WARE);
        // 发送消息
        String wareJson = initWareOrder(orderId);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK,wareJson);
    }



    /**
     * 发送减库存消息的字符串
     * @param orderId
     * @return
     */
    // 根据orderId 获取json 字符串
    private String initWareOrder(Long orderId) {
        // 通过orderId 获取orderInfo
        OrderInfo orderInfo = getOrderInfo(orderId);

        // 将orderInfo中部分数据转换为Map
        Map map = initWareOrder(orderInfo);

        return JSON.toJSONString(map);
    }

    //  将orderInfo中部分数据转换为Map
    public Map initWareOrder(OrderInfo orderInfo) {

        // 发送的字符串是orderInfo 中部分组成
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");
        map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
    /*
    details:[{skuId:101,skuNum:1,skuName:
    ’小米手64G’},
    {skuId:201,skuNum:1,skuName:’索尼耳机’}]
     */
        ArrayList<Map> mapArrayList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            HashMap<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId", orderDetail.getSkuId());
            orderDetailMap.put("skuNum", orderDetail.getSkuNum());
            orderDetailMap.put("skuName", orderDetail.getSkuName());
            mapArrayList.add(orderDetailMap);
        }
        map.put("details", mapArrayList);
        return map;
    }

    /**
     * 获取所有子订单集合
     * @param orderId
     * @param wareSkuMap
     * @return
     */
    @Override
    public List<OrderInfo> orderSplit(String orderId, String wareSkuMap) {
        /**
         * 1.先获取到原始订单
         * 2.需要根据wareMap 转换为能操作的数据
         * 3.生成新的子订单，并赋值，保存子菜单
         * 4.将子订单添加到集合
         * 5.修改原始订单
         */
        // 定义子订单集合
        List<OrderInfo> subOrderInfoList=new ArrayList<>();
        OrderInfo orderInfoOrigin = this.getOrderInfo(Long.parseLong(orderId));
        // [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}],
        List<Map> mapList = JSON.parseArray(wareSkuMap, Map.class);

       if (!CollectionUtils.isEmpty(mapList)){
           for (Map map : mapList) {
               // 仓库id
               String wareId = (String) map.get("wareId");
               List<String> skuIds= (List<String>) map.get("wareId");
               // 创建新的子订单
               OrderInfo subOrderInfo = new OrderInfo();
               // 顺序赋值
               BeanUtils.copyProperties(orderInfoOrigin,subOrderInfo);
               // 总金额{跟订单明细有关}， 父id
               subOrderInfo.sumTotalAmount();
               subOrderInfo.setParentOrderId(Long.parseLong(orderId));
               // id 自增
               subOrderInfo.setId(null);
               // 赋值仓库id
               subOrderInfo.setWareId(wareId);
               // 计算总金额需要商品订单明细
               List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();
              List<OrderDetail> orderDetails=  new ArrayList<>();
               for (OrderDetail orderDetail : orderDetailList) {
                   for (String skuId : skuIds) {
                       if (orderDetail.getSkuId()==Long.parseLong(skuId)){
                               //得到当前仓库订单明细
                            orderDetails.add(orderDetail);
                       }
                   }
               }
               //给订单赋值订单明细
               subOrderInfo.setOrderDetailList(orderDetails);
               subOrderInfo.sumTotalAmount();
               // 保存子订单
               saveOrderInfo(subOrderInfo);
               subOrderInfoList.add(subOrderInfo);
           }
       }
       // 修改原始订单
        this.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.SPLIT);
       // 返回子订单集合
        return subOrderInfoList;
    }


    @Override
    public void execExpiredOrder(Long orderId, String flag) {
        // 执行update 语句
        updateOrderStatus(orderId,ProcessStatus.CLOSED);
        if ("2".equals(flag)){
            // 发送一个消息关闭交易记录
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
        }

    }


}
